package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.config.properties.CmnyProperties;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.DmcCsunVersionSetMapper;
import com.csun.cmny.provider.device.csun.camera.CameraMessageHandler;
import com.csun.cmny.provider.device.csun.gateway.GatewayMessageSender;
import com.csun.cmny.provider.device.csun.sleep.SleepMessageSender;
import com.csun.cmny.provider.model.constant.DeviceConstant;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.version.VersionSetApplyDto;
import com.csun.cmny.provider.model.dto.version.VersionSetDto;
import com.csun.cmny.provider.model.dto.version.VersionSetPersonApply;
import com.csun.cmny.provider.model.dto.version.VersionSetQueryDto;
import com.csun.cmny.provider.model.enums.UacRoleCodeEnum;
import com.csun.cmny.provider.model.enums.device.DeviceFileUrlEnum;
import com.csun.cmny.provider.model.vo.RpcRoleVo;
import com.csun.cmny.provider.model.vo.csunsleep.DmcCsunSleepVo;
import com.csun.cmny.provider.model.vo.csunversion.AppVersionDeviceVo;
import com.csun.cmny.provider.model.vo.csunversion.VersionDeviceVo;
import com.csun.cmny.provider.model.vo.csunversion.VersionSetVo;
import com.csun.cmny.provider.model.vo.device.DmcDeviceVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.util.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2020/4/2 11:26
 * @Description: the class dmc csun version set service impl
 */
@Slf4j
@Service
@Transactional
public class DmcCsunVersionSetServiceImpl extends BaseService<DmcCsunVersionSet> implements DmcCsunVersionSetService {

    @Resource
    private DmcCsunVersionSetMapper dmcCsunVersionSetMapper;
    @Resource
    private DmcCsunVersionSetDeviceService dmcCsunVersionSetDeviceService;
    @Resource
    private DmcCsunVersionFileService dmcCsunVersionFileService;
    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private DmcDeviceService dmcDeviceService;
    @Resource
    private UacRpcService uacRpcService;
    @Resource
    private DmcCsunVersionSetVarService dmcCsunVersionSetVarService;
    @Resource
    private DmcCsunVersionSetRemarkService dmcCsunVersionSetRemarkService;
    @Resource
    private DmcDeviceUserBindService dmcDeviceUserBindService;
    @Resource
    private CameraMessageHandler cameraMessageHandler;
    @Resource
    private GatewayMessageSender gatewayMessageSender;
    @Resource
    private SleepMessageSender sleepMessageSender;
    @Resource
    private CmnyProperties cmnyProperties;
    @Resource
    private DmcCsunSleepBindService dmcCsunSleepBindService;

    /**
     * query csun version set list with page
     *
     * @param versionSetQueryDto    the version set query dto
     *
     * @return  the list
     */
    @Override
    public List<VersionSetVo> queryListWithPage(VersionSetQueryDto versionSetQueryDto) {

        PageHelper.startPage(versionSetQueryDto.getPageNum(), versionSetQueryDto.getPageSize());

        return dmcCsunVersionSetMapper.queryListWithPage(versionSetQueryDto);
    }

    @Override
    public Integer add(VersionSetDto versionSetDto, LoginAuthDto loginAuthDto) {

        // 校验版本Id是否为空
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetDto.getVersionId()),
                cmnyMessageSource.getMessage("csun.version.file.id.null", null));

        // 校验版本Id是否存在
        DmcCsunVersionFile dmcCsunVersionFile = dmcCsunVersionFileService.selectByKey(versionSetDto.getVersionId());
        Preconditions.checkArgument(dmcCsunVersionFile != null,
                cmnyMessageSource.getMessage("csun.version.file.not.exist", null));

        // 校验设备Id集合是否为空
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetDto.getDeviceIdList()),
                cmnyMessageSource.getMessage("csun.version.device.id.list.null", null));

        // 校验发布内容是否为空
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetDto.getContent()),
                cmnyMessageSource.getMessage("csun.version.set.content.null", null));

        // 校验下载地址是否为空
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetDto.getFileUrl()),
                cmnyMessageSource.getMessage("csun.version.set.file.url.null", null));

        // 校验下载地址是否合法
        DeviceFileUrlEnum fileUrlEnum = DeviceFileUrlEnum.getEnum(versionSetDto.getFileUrl());
        Preconditions.checkArgument(PublicUtil.isNotEmpty(fileUrlEnum),
                cmnyMessageSource.getMessage("csun.version.set.file.url.error", null));

        // 根据设备Id查询设备
        List<DmcDeviceVo> dmcDeviceList = dmcDeviceService.queryDeviceListByIdList(versionSetDto.getDeviceIdList());
        Map<Long, DmcDeviceVo> deviceVoMap = Maps.newHashMap();
        if (PublicUtil.isNotEmpty(dmcDeviceList)) {
            deviceVoMap = dmcDeviceList.stream()
                    .collect(Collectors.toMap(DmcDeviceVo::getId, a -> a,(k1, k2)->k1));
        }

        // 保存版本配置
        DmcCsunVersionSet dmcCsunVersionSet = new DmcCsunVersionSet();
        dmcCsunVersionSet.setVersionId(versionSetDto.getVersionId());
        dmcCsunVersionSet.setContent(versionSetDto.getContent());
        dmcCsunVersionSet.setFileUrl(cmnyProperties.getDevice().getFile().getUrl() + versionSetDto.getFileUrl());
        dmcCsunVersionSet.setStat(DeviceConstant.VERSION_SET_DEPLOY);
        dmcCsunVersionSet.setUpdateInfo(loginAuthDto);
        Integer result = dmcCsunVersionSetMapper.insertSelective(dmcCsunVersionSet);

        List<DmcCsunVersionSetDevice> versionSetDeviceList = Lists.newArrayList();
        for (Long deviceId : versionSetDto.getDeviceIdList()) {
            DmcDeviceVo device = deviceVoMap.get(deviceId);
            DmcCsunVersionSetDevice vsd = new DmcCsunVersionSetDevice();
            vsd.setVersionSetId(dmcCsunVersionSet.getId());
            vsd.setDeviceId(deviceId);
            vsd.setAfterVersion(dmcCsunVersionFile.getFileVersion());
            if (PublicUtil.isEmpty(device)) {   // 设备不存在
                vsd.setStat(DeviceConstant.DEVICE_UPDATE_STAT_NOT);
            } else {
                vsd.setDeviceNo(device.getDeviceNo());
                if (dmcCsunVersionFile.getFileType().equals(device.getDeviceType())) {
                    // 个人设备 - 用户确认是否升级
                    // 企业设备 - 走审批流程

                    vsd.setBeforeVersion(device.getDeviceVersion());
                    vsd.setStat(DeviceConstant.DEVICE_UPDATE_STAT_SET);
                } else {    // 设备类型不对
                    vsd.setStat(DeviceConstant.DEVICE_UPDATE_STAT_EQ);
                }
            }

            versionSetDeviceList.add(vsd);
        }

        result += dmcCsunVersionSetDeviceService.batchSave(versionSetDeviceList);

        // 添加批注


        return result;
    }

    @Override
    public List<VersionDeviceVo> queryDetailListWithPage(VersionSetQueryDto versionSetQueryDto) {

        PageHelper.startPage(versionSetQueryDto.getPageNum(), versionSetQueryDto.getPageSize());

        return dmcCsunVersionSetMapper.queryDetailListWithPage(versionSetQueryDto);
    }

    /**
     * query cur task states
     *
     * @param loginAuthDto the login auth dto
     * @return the list.
     */
    @Override
    public List<Integer> queryCurTaskStates(LoginAuthDto loginAuthDto) {

        List<Integer> states = Lists.newArrayList();

        // 获取当前用户角色
        List<RpcRoleVo> roleVoList = uacRpcService.queryRoleListByUserId(loginAuthDto.getUserId());

        for (RpcRoleVo r : roleVoList) {
            if (r.getRoleCode().equals(UacRoleCodeEnum.SHOUHOU.getCode())) {
                // 服务部长角色（服务部长） ===> 查看提交申请的任务
                states.add(DeviceConstant.VERSION_SET_DEPLOY);
            }
            if (r.getRoleCode().equals(UacRoleCodeEnum.BOSS.getCode())) {
                states.add(DeviceConstant.VERSION_SET_SH_YES);
            }
        }

        return states;
    }

    /**
     * 售后审批
     *
     * @param versionSetApplyDto the version set apply dto
     * @return the int.
     */
    @Override
    public Integer shouHouApply(VersionSetApplyDto versionSetApplyDto, LoginAuthDto loginAuthDto) {

        int stat = DeviceConstant.VERSION_SET_SH_YES;

        // 校验参数 - 版本设置Id
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetApplyDto.getVersionSetId()),
                cmnyMessageSource.getMessage("csun.version.set.id.null", null));

        // 校验版本升级任务是否存在
        DmcCsunVersionSet dmcCsunVersionSet = new DmcCsunVersionSet();
        dmcCsunVersionSet.setId(versionSetApplyDto.getVersionSetId());
        dmcCsunVersionSet.setStat(DeviceConstant.VERSION_SET_DEPLOY);
        dmcCsunVersionSet = dmcCsunVersionSetMapper.selectOne(dmcCsunVersionSet);
        Preconditions.checkArgument(PublicUtil.isNotEmpty(dmcCsunVersionSet),
                cmnyMessageSource.getMessage("csun.version.set.task.null", null));

        // 校验参数 - 审批状态
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetApplyDto.getState()),
                cmnyMessageSource.getMessage("csun.version.apply.state.null", null));

        Preconditions.checkArgument(versionSetApplyDto.getState() >=0 && versionSetApplyDto.getState() <= 1,
                cmnyMessageSource.getMessage("csun.version.apply.state.error", null));

        // 校验参数 - 升级日期
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetApplyDto.getUpdateDate()),
                cmnyMessageSource.getMessage("csun.version.update.date.null", null));

        // 校验参数 - 升级设备Id
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetApplyDto.getDeviceIdList()),
                cmnyMessageSource.getMessage("csun.version.device.id.list.null", null));

        DmcCsunVersionSetRemark dmcCsunVersionSetRemark =  new DmcCsunVersionSetRemark();
        dmcCsunVersionSetRemark.setVersionSetId(versionSetApplyDto.getVersionSetId());

        List<DmcCsunVersionSetVar> dmcCsunVersionSetVarList = Lists.newArrayList();


        if (versionSetApplyDto.getState().compareTo(0) == 0) {
            // 校验参数 - 批注
            Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetApplyDto.getRemark()),
                    cmnyMessageSource.getMessage("csun.version.remark.null", null));

            stat= DeviceConstant.VERSION_SET_SH_NO;
            dmcCsunVersionSetRemark.setRemark(versionSetApplyDto.getRemark());

        } else {
            dmcCsunVersionSetRemark.setRemark("售后审批通过");

            DmcCsunVersionSetVar varUpdateDate = new DmcCsunVersionSetVar();
            varUpdateDate.setVersionSetId(versionSetApplyDto.getVersionSetId());
            varUpdateDate.setName(DeviceConstant.VERSION_VAR_UPDATE_DATE);
            varUpdateDate.setText(versionSetApplyDto.getUpdateDate());
            dmcCsunVersionSetVarList.add(varUpdateDate);

            DmcCsunVersionSetVar varDeviceIdList = new DmcCsunVersionSetVar();
            varDeviceIdList.setVersionSetId(versionSetApplyDto.getVersionSetId());
            varDeviceIdList.setName(DeviceConstant.VERSION_VAR_DEVICE_ID_LIST);

            varDeviceIdList.setText(Joiner.on(",").join(versionSetApplyDto.getDeviceIdList()));
            dmcCsunVersionSetVarList.add(varDeviceIdList);

            dmcCsunVersionSetVarService.batchSave(dmcCsunVersionSetVarList);
        }

        dmcCsunVersionSetRemarkService.save(dmcCsunVersionSetRemark);

        // 改变配置状态
        dmcCsunVersionSet.setStat(stat);
        dmcCsunVersionSet.setUpdateInfo(loginAuthDto);
        Integer result = dmcCsunVersionSetMapper.updateByPrimaryKeySelective(dmcCsunVersionSet);

        /**
         * @date    2020-05-11
         * @author  chisj
         * @desc    个人设备不走审批流程
         */
        List<Long> deviceIdList = dmcDeviceUserBindService
                .queryAllDeviceIdList();

        if (PublicUtil.isNotEmpty(deviceIdList)) {
            versionSetApplyDto.getDeviceIdList().removeAll(deviceIdList);
        }

        // 改变设备配置-设备状态
        result += dmcCsunVersionSetDeviceService.batchUpdateStat(
                versionSetApplyDto.getVersionSetId(), versionSetApplyDto.getDeviceIdList(),
                DeviceConstant.VERSION_SET_DEPLOY, stat);

        return result;
    }

    /**
     * 总经理审批
     *
     * @param versionSetApplyDto the version set apply dto
     *
     * @return the int.
     */
    @Override
    public Integer bossApply(VersionSetApplyDto versionSetApplyDto, LoginAuthDto loginAuthDto) {

        int stat = DeviceConstant.VERSION_SET_BOSS_YES;

        // 校验参数 - 版本设置Id
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetApplyDto.getVersionSetId()),
                cmnyMessageSource.getMessage("csun.version.set.id.null", null));

        // 校验版本升级任务是否存在
        DmcCsunVersionSet dmcCsunVersionSet = new DmcCsunVersionSet();
        dmcCsunVersionSet.setId(versionSetApplyDto.getVersionSetId());
        dmcCsunVersionSet.setStat(DeviceConstant.VERSION_SET_SH_YES);
        dmcCsunVersionSet = dmcCsunVersionSetMapper.selectOne(dmcCsunVersionSet);
        Preconditions.checkArgument(PublicUtil.isNotEmpty(dmcCsunVersionSet),
                cmnyMessageSource.getMessage("csun.version.set.task.null", null));

        // 校验参数 - 审批状态
        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetApplyDto.getState()),
                cmnyMessageSource.getMessage("csun.version.apply.state.null", null));

        Preconditions.checkArgument(versionSetApplyDto.getState() >=0 && versionSetApplyDto.getState() <= 1,
                cmnyMessageSource.getMessage("csun.version.apply.state.error", null));

        DmcCsunVersionSetRemark dmcCsunVersionSetRemark =  new DmcCsunVersionSetRemark();
        dmcCsunVersionSetRemark.setVersionSetId(versionSetApplyDto.getVersionSetId());

        if (versionSetApplyDto.getState().compareTo(0) == 0) {
            // 校验参数 - 批注
            Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetApplyDto.getRemark()),
                    cmnyMessageSource.getMessage("csun.version.remark.null", null));

            stat= DeviceConstant.VERSION_SET_BOSS_NO;
            dmcCsunVersionSetRemark.setRemark(versionSetApplyDto.getRemark());

        } else {
            dmcCsunVersionSetRemark.setRemark("总经理审批通过");
        }

        dmcCsunVersionSetRemarkService.save(dmcCsunVersionSetRemark);

        // 改变配置状态
        dmcCsunVersionSet.setStat(stat);
        dmcCsunVersionSet.setUpdateInfo(loginAuthDto);
        Integer result = dmcCsunVersionSetMapper.updateByPrimaryKeySelective(dmcCsunVersionSet);

        // 查询设备变量
        DmcCsunVersionSetVar dmcCsunVersionSetVar = new DmcCsunVersionSetVar();
        dmcCsunVersionSetVar.setVersionSetId(versionSetApplyDto.getVersionSetId());
        dmcCsunVersionSetVar.setName(DeviceConstant.VERSION_VAR_DEVICE_ID_LIST);
        dmcCsunVersionSetVar = dmcCsunVersionSetVarService.selectOne(dmcCsunVersionSetVar);
        if (PublicUtil.isNotEmpty(dmcCsunVersionSet)) {
            List<Long> deviceIdList = Lists.newArrayList();
            String[] array = dmcCsunVersionSetVar.getText().split(",");
            for (String s : array) {
                deviceIdList.add(Long.parseLong(s));
            }
            // 改变设备配置-设备状态
            result += dmcCsunVersionSetDeviceService.batchUpdateStat(
                    versionSetApplyDto.getVersionSetId(), deviceIdList,
                    DeviceConstant.VERSION_SET_SH_YES, stat);
        }

        return result;
    }

    /**
     * 个人用户设备升级
     *
     * @param versionSetPersonApply the version set person apply
     * @return the int.
     */
    @Override
    public Integer personApply(VersionSetPersonApply versionSetPersonApply) {

        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetPersonApply.getVersionSetId()),
                cmnyMessageSource.getMessage("csun.version.set.id.null", null));

        Preconditions.checkArgument(PublicUtil.isNotEmpty(versionSetPersonApply.getDeviceId()),
                cmnyMessageSource.getMessage("device.id.null", null));

        // 查询是否存在待升级设备
        DmcCsunVersionSetDevice dmcCsunVersionSetDevice = new DmcCsunVersionSetDevice();
        dmcCsunVersionSetDevice.setDeviceId(versionSetPersonApply.getDeviceId());
        dmcCsunVersionSetDevice.setVersionSetId(versionSetPersonApply.getVersionSetId());
        dmcCsunVersionSetDevice = dmcCsunVersionSetDeviceService.selectOne(dmcCsunVersionSetDevice);
        Preconditions.checkArgument(PublicUtil.isNotEmpty(dmcCsunVersionSetDevice),
                cmnyMessageSource.getMessage("csun.version.set.task.null", null));

        VersionSetVo versionSetVo = dmcCsunVersionSetMapper.queryVersionSetVoById(versionSetPersonApply.getVersionSetId());

        DmcDevice dmcDevice = dmcDeviceService.selectByKey(versionSetPersonApply.getDeviceId());

        // 根据版本类型 下发不同的升级指令
        switch (versionSetVo.getFileType()) {
            case DeviceConstant.CSUN_CAMERA :
                cameraMessageHandler.sendUpdateVersionMsg(Lists.newArrayList(dmcDevice), versionSetVo);
                break;
            case DeviceConstant.CSUN_GATEWAY :
                gatewayMessageSender.sendUpdateVerMsg(Lists.newArrayList(dmcDevice), versionSetVo);
                break;
            case DeviceConstant.CSUN_SLEEP :
                sleepMessageSender.sendUpdateVerMsg(Lists.newArrayList(dmcDevice), versionSetVo);
                break;
            default:
                log.warn("未定义升级指令下发流程.");
                break;
        }

        dmcCsunVersionSetDevice.setStat(DeviceConstant.VERSION_SET_PERSON_YES);

        return dmcCsunVersionSetDeviceService.update(dmcCsunVersionSetDevice);
    }

    /**
     * 根据升级时间获取升级配置
     *
     * @param time the time
     * @return the list.
     */
    @Override
    public List<VersionSetVo> queryVersionSetVoList(String time) {

        Map<String, Object> param = new HashMap<>();
        param.put("name", DeviceConstant.VERSION_VAR_UPDATE_DATE);
        param.put("text", time);
        param.put("stat", DeviceConstant.VERSION_SET_BOSS_YES);

        return dmcCsunVersionSetMapper.queryVersionSetVoList(param);
    }

    /**
     * query apply var by id
     *
     * @param versionSetId  the version set id
     *
     * @return  the map
     */
    @Override
    public Map<String,Object> queryApplyVarById(Long versionSetId) {

        Map<String, Object> param = new HashMap<>();

        DmcCsunVersionSetVar updateDate = new DmcCsunVersionSetVar();
        updateDate.setVersionSetId(versionSetId);
        updateDate.setName(DeviceConstant.VERSION_VAR_UPDATE_DATE);
        updateDate = dmcCsunVersionSetVarService.selectOne(updateDate);
        if (PublicUtil.isNotEmpty(updateDate)) {
            param.put(DeviceConstant.VERSION_VAR_UPDATE_DATE, updateDate.getText());
        } else {
            param.put(DeviceConstant.VERSION_VAR_UPDATE_DATE, "");
        }

        DmcCsunVersionSetVar deviceIdList = new DmcCsunVersionSetVar();
        deviceIdList.setVersionSetId(versionSetId);
        deviceIdList.setName(DeviceConstant.VERSION_VAR_DEVICE_ID_LIST);
        deviceIdList =  dmcCsunVersionSetVarService.selectOne(deviceIdList);
        if (PublicUtil.isNotEmpty(deviceIdList)) {
            //
            String[] stringList = deviceIdList.getText().split(",");
            List<Long> list = Lists.newArrayList();
            for (int i = 0; i < stringList.length; i++) {
                list.add(Long.parseLong(stringList[i]));
            }
            List<DmcDeviceVo> dmcDeviceVos = dmcDeviceService.queryDeviceListByIdList(list);
            param.put(DeviceConstant.VERSION_VAR_DEVICE_ID_LIST, dmcDeviceVos);
        } else {
            param.put(DeviceConstant.VERSION_VAR_DEVICE_ID_LIST, Lists.newArrayList());
        }

        return param;
    }

    /**
     * query update version list
     *
     * @param loginAuthDto the login auth dto
     *
     * @return the list
     */
    @Override
    public List<AppVersionDeviceVo> queryUpdateVersionList(LoginAuthDto loginAuthDto) {

        // 查询用户的设备Id集合
        List<Long> deviceIdList = dmcDeviceUserBindService.queryDeviceIdList(loginAuthDto.getUserId());

        if (PublicUtil.isEmpty(deviceIdList)) {
            return null;
        }

        // 根据设备Id集合查询最新的升级配置
        return dmcCsunVersionSetMapper.queryUpdateVersionList(deviceIdList);
    }

//    @Test
//    public void test() {
//
//        List<Long> m = Lists.newArrayList();
//        m.add(1l);
//        m.add(2l);
//        m.add(3l);
//
//        List<Long> n = Lists.newArrayList();
//        n.add(3l);
//        m.add(4l);
//
//        m.removeAll(n);
//
//        System.out.println("list = " + m.toString());
//    }
}
